home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PRINTER / JPSRC11.ARJ / JETUTIL.C < prev    next >
C/C++ Source or Header  |  1991-08-04  |  11KB  |  429 lines

  1. /*
  2.  *      JET PAK - HP DeskJet and LaserJet series printer utilities
  3.  *
  4.  *      JETUTIL module - miscellaneous utilities
  5.  *
  6.  *      Version 1.1 (Public Domain)
  7.  */
  8.  
  9. /* system include files */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13.  
  14. #ifdef __MSDOS__
  15.  
  16. /* MS-DOS platform specific include files */
  17. #include <dir.h>
  18. #include <dos.h>
  19. #include <time.h>
  20.  
  21. #endif /* __MSDOS__ */
  22.  
  23. /* application include files */
  24. #include "jetutil.h"
  25.  
  26.  
  27. /*
  28.  * OPTION PROCESSING UTILITY FUNCTIONS
  29.  */
  30.  
  31. char *optarg = "";      /* option argument (if any) */
  32. int optind = 1;         /* argv[] index currently being examined */
  33. int opterr = TRUE;      /* whether getopt() should print error messages */
  34.  
  35. static int optpos = 0;  /* position in argv[optind] being examined */
  36.  
  37. #define OPTCHAR     '-'
  38. #define OPTARGCHAR  ':'
  39. #define OPTBAD      '?'
  40.  
  41. int getopt(argc, argv, optstring)
  42. int argc;
  43. char *argv[];
  44. char *optstring;
  45. {
  46.     /*
  47.      * This function should behave like the UNIX getopt():
  48.      *
  49.      * It returns the next option letter in 'argv[]' that matches a
  50.      * letter in 'optstring'. 'optstring' is a string of recognised
  51.      * option letters; if a letter is followed by ':' (OPTARGCHAR), the
  52.      * option is expected to have an argument, which may or may not
  53.      * be separated from it by white space; 'optarg' is then set to point
  54.      * to the start of the option argument.
  55.      *
  56.      * When all options have been processed, getopt() returns EOF.
  57.      * The special option '--' can be used to mark the end of the
  58.      * options.
  59.      *
  60.      * On error, '?' (OPTBAD) is returned; if 'opterr' is TRUE, an
  61.      * error message is also printed.
  62.      */
  63.     char *osp;
  64.  
  65.     /* check index to argument is in range */
  66.     if (optind < 1 || optind >= argc)
  67.         return(EOF);
  68.  
  69.     if (optpos == 0)
  70.     {
  71.         /* check argument is an option */
  72.         if (argv[optind][optpos] != OPTCHAR)
  73.             return(EOF);
  74.  
  75.         /* check for explicit argument termination */
  76.         if (argv[optind][++optpos] == OPTCHAR)
  77.         {
  78.             optpos = 0;
  79.             optind++;
  80.  
  81.             return(EOF);
  82.         }
  83.     }
  84.  
  85.     /* check option is valid */
  86.     if (!(osp = strchr(optstring, argv[optind][optpos])))
  87.     {
  88.         if (opterr)
  89.             fprintf(stderr, ERROR_OPTION_BAD, argv[optind][optpos]);
  90.  
  91.         if (argv[optind][++optpos] == '\0')
  92.         {
  93.             optpos = 0;
  94.             optind++;
  95.         }
  96.  
  97.         return(OPTBAD);
  98.     }
  99.  
  100.     if (osp[1] == OPTARGCHAR)
  101.     {
  102.         /* argument is expected */
  103.         if (argv[optind][++optpos] == '\0')
  104.         {
  105.             optind++;
  106.             if (optind >= argc)
  107.             {
  108.                 fprintf(stderr, ERROR_OPTION_NO_ARG, osp[0]);
  109.                 return(OPTBAD);
  110.             }
  111.  
  112.             optarg = argv[optind];
  113.         }
  114.         else
  115.         {
  116.             optarg = &argv[optind][optpos];
  117.         }
  118.  
  119.         optpos = 0;
  120.         optind++;
  121.     }
  122.     else
  123.     {
  124.         /* no arguments required */
  125.         optarg = "";
  126.  
  127.         if (argv[optind][++optpos] == '\0')
  128.         {
  129.             optpos = 0;
  130.             optind++;
  131.         }
  132.     }
  133.  
  134.     return(osp[0]);
  135. }
  136.  
  137. /*
  138.  * DIRECTORY SEARCHING UTILITY FUNCTIONS
  139.  */
  140.  
  141. /* the following exported variables point to the next matching file
  142.    and containing directory to be processed when os_getfile()
  143.    returns OK */
  144. char *os_file = NULL;
  145. char *os_dir = NULL;
  146.  
  147. /* definitions of list nodes used to hold directories and files */
  148. struct filenode {
  149.     struct filenode *next;
  150.     char *name;
  151. };
  152.  
  153. struct dirnode {
  154.     struct dirnode *next;
  155.     char *name;
  156.     struct filenode *file;
  157. };
  158.  
  159. static struct dirnode *dirnodeptr = NULL;
  160.  
  161. int os_findfiles(argc, argv)
  162. int argc;
  163. char *argv[];
  164. {
  165.     /*
  166.      * This function builds a tree structure recording the files
  167.      * selected for processing by the user, and their containing
  168.      * directories.
  169.      *
  170.      * This is needed for MS-DOS to get around the problem that
  171.      * if wildcard matching is done continuously while a program
  172.      * is running, the output files created by the program can
  173.      * start to be matched, and this is not a good thing. For
  174.      * example, JETL2D *.* would cause problems if more than one
  175.      * input file existed in the directory to start with.
  176.      *
  177.      * Path names are split up into directory and file parts so
  178.      * that the output files may be built in the current directory,
  179.      * even if the input files are prefixed with a different
  180.      * directory name.
  181.      *
  182.      * Space is allocated from the heap for the elements of the
  183.      * structure. If there isn't sufficient heap space to
  184.      * build the structure, ERROR is returned. Otherwise OK is
  185.      * returned.
  186.      */
  187. #ifdef  __MSDOS__
  188.     struct ffblk findblock;
  189. #endif  /* __MSDOS__ */
  190.     char *asp;
  191.     struct dirnode *dnp;
  192.     struct filenode *fnp;
  193.     int arg;
  194.  
  195.     for (arg = 0; arg < argc; arg++)
  196.     {
  197.         if (dirnodeptr == NULL)
  198.         {
  199.             if ((dirnodeptr = zalloc(sizeof(struct dirnode))) == NULL)
  200.                 return(ERROR);
  201.  
  202.             dnp = dirnodeptr;
  203.         }
  204.         else
  205.         {
  206.             if ((dnp->next = zalloc(sizeof(struct dirnode))) == NULL)
  207.                 return(ERROR);
  208.  
  209.             dnp = dnp->next;
  210.         }
  211.  
  212.         /* PLATFORM_DEPENDENT: directory/file separator */
  213. #ifdef  __MSDOS__
  214. #define PATHNAME_SEPARATOR '\\'
  215. #else
  216. #define PATHNAME_SEPARATOR '/'
  217. #endif
  218.         if ((asp = strrchr(argv[arg], PATHNAME_SEPARATOR)) != NULL)
  219.         {
  220.             /* directory specified in path */
  221.             if ((dnp->name = zalloc((size_t)((asp - argv[arg]) + 2))) == NULL)
  222.                 return(ERROR);
  223.             strncpy(dnp->name, argv[arg], (size_t)((asp - argv[arg]) + 1));
  224.         }
  225. #ifdef  __MSDOS__
  226.         else if ((asp = strrchr(argv[arg], ':')) != NULL)
  227.         {
  228.             /* drive name specified in path */
  229.             if ((dnp->name = zalloc((size_t)((asp - argv[arg]) + 2))) == NULL)
  230.                 return(ERROR);
  231.             strncpy(dnp->name, argv[arg], (size_t)((asp - argv[arg]) + 1));
  232.         }
  233. #endif  /* __MSDOS__ */
  234.         else
  235.         {
  236.             /* set directory to "" */
  237.             if ((dnp->name = zalloc(1)) == NULL)
  238.                 return(ERROR);
  239.         }
  240.  
  241. #ifdef  __MSDOS__
  242.  
  243.         if (findfirst(argv[arg], &findblock, 0) == 0)
  244.         {
  245.             if ((fnp = zalloc(sizeof(struct filenode))) == NULL)
  246.                 return(ERROR);
  247.             dnp->file = fnp;
  248.  
  249.             if ((fnp->name = zalloc(1+strlen(findblock.ff_name))) == NULL)
  250.                 return(ERROR);
  251.             strcpy(fnp->name, findblock.ff_name);
  252.             strlwr(fnp->name);  /* for consistent lower case naming */
  253.  
  254.             while(findnext(&findblock) == 0)
  255.             {
  256.                 if ((fnp->next = zalloc(sizeof(struct filenode))) == NULL)
  257.                     return(ERROR);
  258.                 fnp = fnp->next;
  259.  
  260.                 if ((fnp->name = zalloc(1+strlen(findblock.ff_name))) == NULL)
  261.                     return(ERROR);
  262.                 strcpy(fnp->name, findblock.ff_name);
  263.                 strlwr(fnp->name);
  264.             }
  265.         }
  266.         else
  267.         {
  268.             fprintf(stderr, ERROR_NO_FILES_MATCHED, argv[arg]);
  269.         }
  270.  
  271. #else /* __MSDOS__ */
  272.  
  273.         /* PLATFORM_DEPENDENT: if a non-MSDOS platform requires the
  274.            program to implement wildcard matching itself (ie like MS-DOS),
  275.            then the necessary code to do that could be added in here */
  276.  
  277.         if ((fnp = zalloc(sizeof(struct filenode))) == NULL)
  278.             return(ERROR);
  279.         dnp->file = fnp;
  280.  
  281.         /* point asp at start of file name */
  282.         if (asp == NULL)
  283.             asp = argv[arg];
  284.         else
  285.             asp++;
  286.  
  287.         if ((fnp->name = zalloc(1+strlen(asp))) == NULL)
  288.             return(ERROR);
  289.         strcpy(fnp->name, asp);
  290.  
  291. #endif  /* __MSDOS__ */
  292.  
  293.     }
  294.  
  295.     return(OK);
  296. }
  297.  
  298. int os_getfile()
  299. {
  300.     /*
  301.      * This function is called after os_findfiles() to select in turn
  302.      * each file required to be processed.
  303.      *
  304.      * If os_getfile() finds a file to be processed, it sets the
  305.      * 'os_dir' and 'os_file' globals to point to the containing
  306.      * directory and file name, and returns OK. If there are no
  307.      * more files to be processed, EOF is returned.
  308.      *
  309.      * os_getfile() walks through the node structure built by
  310.      * os_findfiles(), transferring the node pointers to os_dir
  311.      * and os_file, then freeing the heap space once they are
  312.      * no longer needed.
  313.      */
  314.     struct dirnode *dnp;
  315.     struct filenode *fnp;
  316.  
  317.     /* loop through directories looking for a file */
  318.     while ((dnp = dirnodeptr) != NULL)
  319.     {
  320.         /* first time through for a directory, move its name to os_dir */
  321.         if (dnp->name != NULL)
  322.         {
  323.             if (os_dir != NULL)
  324.                 free(os_dir);
  325.             os_dir = dnp->name;
  326.             dnp->name = NULL;
  327.         }
  328.  
  329.         while ((fnp = dnp->file) != NULL)
  330.         {
  331.             /* move file name to os_file */
  332.             if (fnp->name != NULL)
  333.             {
  334.                 if (os_file != NULL)
  335.                     free(os_file);
  336.                 os_file = fnp->name;
  337.                 dnp->file = fnp->next;
  338.                 free(fnp);
  339.                 return(OK);
  340.             }
  341.  
  342.             dnp->file = fnp->next;
  343.             free(fnp);
  344.         }
  345.  
  346.         /* no more files in directory, so free node */
  347.         dirnodeptr = dnp->next;
  348.         free(dnp);
  349.     }
  350.  
  351.     /* no more files to be processed, free remaining heap space */
  352.     if (os_dir != NULL)
  353.         free(os_dir);
  354.     if (os_file != NULL)
  355.         free(os_file);
  356.  
  357.     return(EOF);
  358. }
  359.  
  360. /*
  361.  *  PRINTING UTILITY FUNCTIONS
  362.  */
  363.  
  364. void os_printstr(s)
  365. char *s;
  366. {
  367.     /*
  368.      * Print NULL terminated string 's'
  369.      */
  370.  
  371. #ifdef  __MSDOS__
  372.  
  373.     while (*s) bdos(5, *s++, 0);
  374.  
  375. #else   /* __MSDOS__ */
  376.  
  377.     /* PLATFORM_DEPENDENT: do whatever you have to do to print a
  378.        string on a non-MSDOS platform here */
  379.     while (*s)
  380.     {
  381.         putchar(*s);
  382.         s++;
  383.     }
  384.  
  385. #endif  /* __MSDOS__ */
  386. }
  387. void os_printbuf(s, n)
  388. char *s;
  389. int n;
  390. {
  391.     /*
  392.      * Print buffer 's' of length 'n', which may contain NULLs
  393.      */
  394.  
  395. #ifdef  __MSDOS__
  396.  
  397.     while (n-- > 0) bdos(5, *s++, 0);
  398.  
  399. #else   /* __MSDOS__ */
  400.  
  401.     /* PLATFORM_DEPENDENT: do whatever you have to do to print a
  402.        buffer on a non-MSDOS platform here */
  403.     while (n-- > 0)
  404.     {
  405.         putchar(*s);
  406.         s++;
  407.     }
  408.  
  409. #endif  /* __MSDOS__ */
  410. }
  411.  
  412. /*
  413.  *  MEMORY ALLOCATION FUNCTIONS
  414.  */
  415.  
  416. void *zalloc(nbytes)
  417. size_t nbytes;
  418. {
  419.     /*
  420.      *  Allocate and clear nbytes of memory. This routine succeeds
  421.      *  even if nbytes is 0
  422.      */
  423.  
  424.     if (nbytes == 0)
  425.         nbytes++;
  426.  
  427.     return(calloc(1, nbytes));
  428. }
  429.